package com.xy.service.mainData;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xy.api.exception.BizException;
import com.xy.api.model.dto.mainData.*;
import com.xy.api.model.dto.system.UserInfoDTO;
import com.xy.api.model.request.mainData.ProductRequest;
import com.xy.api.model.request.mainData.VendorProductRequest;
import com.xy.api.model.response.Rows;
import com.xy.api.service.mainData.IProductInstanceService;
import com.xy.api.service.mainData.IProductService;
import com.xy.api.service.mainData.IVendorProductTypeService;
import com.xy.api.service.mainData.IVendorService;
import com.xy.auth.UserContext;
import com.xy.mapper.mainData.ProductMapper;
import com.xy.model.condition.mainData.ProductCondition;
import com.xy.model.po.mainData.ProductPO;
import com.xy.utils.CustomBeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements IProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private IVendorService vendorService;

    @Autowired
    private IVendorProductTypeService vendorProductTypeService;

    @Autowired
    private IProductInstanceService productInstanceService;

    @Override
    public Rows<ProductDTO> queryProductList(ProductRequest request) {
        ProductCondition condition = new ProductCondition();
        condition.setName(request.getName());
        Rows<ProductDTO> rows = queryProductList(condition, request.getPageSize(), request.getPageNum());
        fillVendor(rows.getRows());
        fillVendorProductType(rows.getRows());
        return rows;
    }

    /**
     * 填充供货商名称
     *
     * @param productList
     */
    private void fillVendor(List<ProductDTO> productList) {
        if (CollectionUtils.isEmpty(productList)) {
            return;
        }
        List<Long> vendorIds = productList.stream().map(e -> e.getVendorId()).distinct().collect(Collectors.toList());
        Map<Long, VendorDTO> vendorMap = vendorService.getVendorByIds(vendorIds);
        for (ProductDTO productDTO : productList) {
            Long vendorId = productDTO.getVendorId();
            if (vendorMap.containsKey(vendorId)) {
                VendorDTO vendor = vendorMap.get(vendorId);
                productDTO.setVendorName(vendor.getName());
            }
        }
    }

    /**
     * 填充供货商产品类型
     *
     * @param productList
     */
    private void fillVendorProductType(List<ProductDTO> productList) {
        if (CollectionUtils.isEmpty(productList)) {
            return;
        }
        List<Long> vendorProductTypeIds = productList.stream().map(e -> e.getVendorProductTypeId()).distinct().collect(Collectors.toList());
        Map<Long, VendorProductTypeDTO> vendorProductTypeMap = vendorProductTypeService.getVendorProductTypeByIds(vendorProductTypeIds);
        for (ProductDTO productDTO : productList) {
            Long vendorProductTypeId = productDTO.getVendorProductTypeId();
            if (vendorProductTypeMap.containsKey(vendorProductTypeId)) {
                VendorProductTypeDTO vendorProductType = vendorProductTypeMap.get(vendorProductTypeId);
                productDTO.setVendorProductTypeName(vendorProductType.getName());
            }
        }
    }

    @Override
    public Rows<ProductDTO> queryVendorProductList(VendorProductRequest request) {
        Assert.notNull(request.getVendorId(), "供应商ID必填");
        ProductCondition condition = new ProductCondition();
        condition.setVendorId(request.getVendorId());
        condition.setName(request.getName());
        return queryProductList(condition, request.getPageSize(), request.getPageNum());
    }

    /**
     * 查询列表
     *
     * @param condition 条件
     * @param pageSize
     * @param pageNum
     * @return
     */
    private Rows<ProductDTO> queryProductList(ProductCondition condition, Integer pageSize, Integer pageNum) {
        Rows<ProductDTO> result = new Rows<>();
        LambdaQueryWrapper<ProductPO> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(ProductPO::getIsDeleted, false);
        if (StringUtils.hasText(condition.getName())) {
            productWrapper.like(ProductPO::getName, "%" + condition.getName() + "%");
        }
        if (null != condition.getVendorId()) {
            productWrapper.eq(ProductPO::getVendorId, condition.getVendorId());
        }
        pageSize = null != pageSize ? pageSize : 10;
        pageNum = null != pageNum ? pageNum : 1;
        Page<ProductPO> productPOPage = new Page<>(pageNum, pageSize);
        productPOPage = productMapper.selectPage(productPOPage, productWrapper);

        result.setTotal(productPOPage.getTotal());
        result.setRows(CustomBeanUtil.copyListProperties(productPOPage.getRecords(), ProductDTO::new));
        return result;
    }

    @Override
    public Rows<ProductDTO> queryAllProductList() {
        Rows<ProductDTO> result = new Rows<>();
        LambdaQueryWrapper<ProductPO> productWrapper = new LambdaQueryWrapper<>();
        productWrapper.eq(ProductPO::getIsDeleted, false);
        List<ProductPO> productPOS = productMapper.selectList(productWrapper);

        result.setTotal(productPOS.size());
        result.setRows(CustomBeanUtil.copyListProperties(productPOS, ProductDTO::new));
        return result;
    }

    @Override
    public ProductDTO queryProductDetail(Long id) {
        Assert.notNull(id, "产品ID必填");
        ProductPO productPO = productMapper.selectById(id);
        ProductDTO product = new ProductDTO();
        CustomBeanUtil.copyProperties(productPO, product);
        return product;
    }

    @Override
    public void editProduct(ProductDTO request) {
        if (null != request.getId()) {
            updateProduct(request);
        } else {
            addProduct(request);
        }
    }

    /**
     * 新增产品
     *
     * @param product
     */
    private void addProduct(ProductDTO product) {
        ProductPO record = new ProductPO();
        CustomBeanUtil.copyProperties(product, record);

        UserInfoDTO userInfo = UserContext.get();
//        record.setCreateBy(userInfo.getId());

        productMapper.insert(record);
    }

    /**
     * 更新产品
     *
     * @param product
     */
    private void updateProduct(ProductDTO product) {
        Assert.notNull(product.getId(), "产品ID不能为空");
        ProductPO record = new ProductPO();
        CustomBeanUtil.copyProperties(product, record);

        UserInfoDTO userInfo = UserContext.get();
//        record.setUpdateBy(userInfo.getId());

        ProductPO existProduct = productMapper.selectById(product.getId());
        if (!Objects.equals(existProduct.getVendorProductTypeId(), product.getVendorProductTypeId())) {
            productMapper.clearVendorProductTypeId(product.getId());
        }

        productMapper.updateById(record);
    }

    @Override
    public void deleteProduct(Long id) {
        Assert.notNull(id, "产品ID不能为空");
        ProductPO record = new ProductPO();
        record.setId(id);
        record.setIsDeleted(true);
        productMapper.updateById(record);
    }

    @Override
    public List<ProductDTO> queryProductByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProductPO> query = new LambdaQueryWrapper<>();
        query.eq(ProductPO::getIsDeleted, 0)
                .in(ProductPO::getId, ids);
        List<ProductPO> productPOS = productMapper.selectList(query);
        return CustomBeanUtil.copyListProperties(productPOS, ProductDTO::new);
    }

    @Override
    public List<ProductTreeNodeDTO> queryProductTree(Long vendorId, Long vendorProductTypeId) {
        LambdaQueryWrapper<ProductPO> productQuery = new LambdaQueryWrapper<>();
        productQuery
                .eq(ProductPO::getIsDeleted, 0)
                .eq(ProductPO::getVendorProductTypeId, vendorProductTypeId)
                .eq(ProductPO::getVendorId, vendorId);
        List<ProductPO> productPOS = productMapper.selectList(productQuery);

        if (CollectionUtils.isEmpty(productPOS)) {
            throw new BizException("该供应商旗下未添加产品及产品细则");
        }
        List<Long> productIdList = productPOS.stream().map(ProductPO::getId).collect(Collectors.toList());
        List<ProductInstanceDTO> productInstanceDTOS = productInstanceService.queryProductInstanceByProductIds(productIdList);
        if (CollectionUtils.isEmpty(productInstanceDTOS)) {
            throw new BizException("该供应商旗下未添加产品及产品细则");
        }
        List<ProductTreeNodeDTO> productTree = buildProductTree(productPOS, productInstanceDTOS);
        return productTree;
    }


    private List<ProductTreeNodeDTO> buildProductTree(List<ProductPO> productPOS, List<ProductInstanceDTO> productInstanceDTOS) {
        List<ProductTreeNodeDTO> productTree = toProductTreeNode(productPOS);
        List<ProductTreeNodeDTO> productTreeNode = toProductTreeNodeFromInstance(productInstanceDTOS);
        Map<Long, List<ProductTreeNodeDTO>> productIdMap = productTreeNode.stream().collect(Collectors.groupingBy(ProductTreeNodeDTO::getProductId));
        for (ProductTreeNodeDTO levelOneNode : productTree) {
            Long productId = levelOneNode.getProductId();
            if (productIdMap.containsKey(productId)) {
                List<ProductTreeNodeDTO> children = productIdMap.get(productId);
                levelOneNode.setChildren(children);
                String variantCodeOne = levelOneNode.getVariantCodeOne();
                String variantCodeTwo = levelOneNode.getVariantCodeTwo();
                for (ProductTreeNodeDTO node : children) {
                    String variantCodeOneValueWithDesc = variantCodeOne + "-" + node.getVariantCodeOneValue();
                    String variantCodeTwoValueWithDesc = variantCodeTwo + "-" + node.getVariantCodeTwoValue();
                    node.setVariantCodeOneValueWithDesc(variantCodeOneValueWithDesc);
                    node.setVariantCodeTwoValueWithDesc(variantCodeTwoValueWithDesc);
                }
            }
        }
        return productTree;
    }

    private List<ProductTreeNodeDTO> toProductTreeNode(List<ProductPO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<ProductTreeNodeDTO> productTreeNodeList = new ArrayList<>();
        for (ProductPO productPO : list) {
            ProductTreeNodeDTO node = new ProductTreeNodeDTO();
            node.setId(productPO.getId().toString());
            node.setProductId(productPO.getId());
            node.setProductName(productPO.getName());
            node.setVariantCodeOne(productPO.getVariantCodeOne());
            node.setVariantCodeTwo(productPO.getVariantCodeTwo());
            node.setWeightCalculate(productPO.getWeightCalculate());
            productTreeNodeList.add(node);
        }
        return productTreeNodeList;
    }

    private List<ProductTreeNodeDTO> toProductTreeNodeFromInstance(List<ProductInstanceDTO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<ProductTreeNodeDTO> productTreeNodeList = new ArrayList<>();
        for (ProductInstanceDTO instance : list) {
            ProductTreeNodeDTO node = new ProductTreeNodeDTO();
            node.setId(instance.getProductId() + "-" + instance.getId());
            node.setProductId(instance.getProductId());
            node.setProductName(instance.getProductName());
            node.setProductInstanceId(instance.getId());
            node.setVariantCodeOneValue(instance.getVariantCodeOneValue());
            node.setVariantCodeTwoValue(instance.getVariantCodeTwoValue());
            productTreeNodeList.add(node);
        }
        return productTreeNodeList;
    }
}
